package cn.edu.qfnu.oj.entity;

import cn.edu.qfnu.oj.entity.enums.State;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;

@Entity
@DynamicUpdate
public class Contest implements Serializable {

    private Integer id;  // 比赛ID
    private String content; // 比赛内容
    private LocalDateTime startTime; // 比赛开始时间
    private LocalDateTime endTime; // 比赛结束时间
    private String title; // 比赛的标题
    private State state; // 比赛状态
    private Teacher teacher; //创建这个比赛的老师  一个老师可以创建多个比赛 老师与比赛是一对多
    private Attend attend;  //比赛与提交记录是一对一的关系

    private Set<Student> students = new HashSet<>(); // 比赛与学生是多对多关系
    private List<Submit> submits = new ArrayList<>(); // 比赛于提交与比赛是队队医关系
    private Set<Problem> problems = new HashSet<>(); 

    public Contest() {}

    public Contest(String content, LocalDateTime startTime, LocalDateTime endTime, String title) {
        
        if (!LocalDateTime.now().isBefore(startTime) && !LocalDateTime.now().isAfter(endTime)) {
            this.state = State.UNDERWAY;
        } else if (LocalDateTime.now().isAfter(endTime)) {
            this.state = State.END;
        } else {
            this.state = State.NOT_START_YET;
        }
        this.content = content;
        this.startTime = startTime;
        this.endTime = endTime;
        this.title = title;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "content")
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Column(name = "start_time")
    public LocalDateTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }

    @Column(name = "end_time")
    public LocalDateTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }

    @Column(length = 64)
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column
    @Enumerated(value = EnumType.STRING)
    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Contest contest = (Contest) o;

        return new EqualsBuilder()
                .append(id, contest.id)
                .append(state, contest.state)
                .append(content, contest.content)
                .append(startTime, contest.startTime)
                .append(endTime, contest.endTime)
                .append(title, contest.title)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(id)
                .append(content)
                .append(startTime)
                .append(endTime)
                .append(title)
                .append(state)
                .toHashCode();
    }

    //一个参与记录对应一个比赛，一个比赛也对应一个参与记录
    //参与记录与比赛是一对一关系
    @OneToOne(mappedBy = "contest") // 维护比赛与参与记录的一对一关系
    public Attend getAttend() {
        return attend;
    }

    public void setAttend(Attend attend) {
        this.attend = attend;
    }

    // 一个比赛可以被多个学生参加 而这多个学生每人又可以参加多个比赛
    // 所以比赛与学生是多对多关系
    @ManyToMany(mappedBy = "contests") // 比赛与学生的多对多关系由比赛来维护
    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    // 一个比赛可以对应多次提交记录 而这多个提交记录只能同时隶属于一个比赛
    // 所以比赛与提交记录是一对多关系
    @OneToMany(mappedBy = "contest")  // 比赛与提交记录的一对多关系交给提交记录维护
    public List<Submit> getSubmits() {
        return submits;
    }

    public void setSubmits(List<Submit> submitById) {
        this.submits = submitById;
    }

    // 一个老师可以创建多个比赛 而这多个比赛只能隶属于一个老师
    // 所以老师与比赛是一对多关系
    @ManyToOne  // 维护比赛与老师的多对一关系
    @JoinColumn(name = "teacher_id", referencedColumnName = "teacher_id")
    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @ManyToMany
    @JoinTable(name = "submit",
            joinColumns = @JoinColumn(name = "contest_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "problem_id", referencedColumnName = "id"))
    public Set<Problem> getProblems() {
        return problems;
    }

    public void setProblems(Set<Problem> problems) {
        this.problems = problems;
    }
}
